﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace USMC.Net
{
    /// <summary>
    /// Interaction logic for windowedList.xaml
    /// </summary>
    public partial class windowedList : UserControl
    {
        public windowedList()
        {
            InitializeComponent();
            searchingButtonHandle = new MouseButtonEventHandler(pointsListView_MouseUp);
            searchingSelectionHandle = new SelectionChangedEventHandler(pointsListView_SelectionChanged);
            pointsListView.SelectionChanged += searchingSelectionHandle;
            pointsListView.MouseUp += searchingButtonHandle;
            creatingButtonHandle = new MouseButtonEventHandler(pointsListView_MouseUp2);
            pointsStringsDictionary = new Dictionary<string, PointControl>();
            previewMouseDown = new MouseButtonEventHandler(pointsListView_MouseDown);
            pointsListView.PreviewMouseDown += previewMouseDown;
        }
        PointControl openingPoint;
        LinkedListNode<CycleInfo> _currentCycleNode;
        PointControl currentPoint;
        Dictionary<string, PointControl> pointsStringsDictionary;
        MouseButtonEventHandler searchingButtonHandle;
        MouseButtonEventHandler previewMouseDown;
        SelectionChangedEventHandler searchingSelectionHandle;
        MouseButtonEventHandler creatingButtonHandle;
        SelectionChangedEventHandler creatingSelectionHandle;
        bool selectionChanged = false;
        private LinkedListNode<CycleInfo> currentCycleNode
        {
            set
            {
                _currentCycleNode = value;
                pointsListView.SelectedItems.Clear();
                if (_currentCycleNode != null)
                {
                    pointsListView.SelectionChanged -= searchingSelectionHandle;
                    CycleInfo cycle = _currentCycleNode.Value;
                    int i = 0;
                    while (i < pointsListView.Items.Count && pointsStringsDictionary[(string)pointsListView.Items[i]] != cycle.CycleStart)
                        i++;
                    do
                    {
                        pointsListView.SelectedItems.Add(pointsListView.Items[i]);
                        i++;
                    }
                    while (i < pointsListView.Items.Count && pointsStringsDictionary[(string)pointsListView.Items[i]] != cycle.CycleEnd);
                    if(i<pointsListView.Items.Count)
                        pointsListView.SelectedItems.Add(pointsListView.Items[i]);
                    if (i == pointsListView.Items.Count)
                        throw new Exception();
                    countTextBox.Text = _currentCycleNode.Value.Iterations.ToString();
                    removeButton.IsEnabled = true;
                    pointsListView.SelectionChanged += searchingSelectionHandle;
                }
                else
                    removeButton.IsEnabled = false;
            }
            get
            { return _currentCycleNode; }
        }
        public void AssignPointsStack(PointControl point)
        {
            openingPoint = point;
            string val = openingPoint.Number.ToString();
            pointsStringsDictionary.Add(val,openingPoint);
            pointsListView.Items.Add(val);
            PointControl iteratePoint = openingPoint.NextInStack;
            removeButton.IsEnabled = false;
            while (iteratePoint != openingPoint)
            {
                AddPoint(iteratePoint);
                iteratePoint = iteratePoint.NextInStack;
            }
            
        }
        private void AddPoint(PointControl point)
        {
            int p = point.Number;
            string val = p.ToString();
            pointsStringsDictionary.Add(val, point);
            int t = Int32.Parse((string)pointsListView.Items[0]);
            int i=0;
            while (p > t&&i!=pointsListView.Items.Count)
                t = Int32.Parse((string)pointsListView.Items[i++]);
            if (i == pointsListView.Items.Count)
                pointsListView.Items.Add(val);
            else
                pointsListView.Items.Insert(i, val);
            
        }
        public void UnassignPointsStack()
        {
            pointsListView.Items.Clear();
            pointsStringsDictionary.Clear();
            okButton.IsEnabled = false;
            pointsListView.MouseUp -= creatingButtonHandle;
            pointsListView.MouseUp += searchingButtonHandle;
            pointsListView.PreviewMouseDown += previewMouseDown;
            pointsListView.SelectionChanged += searchingSelectionHandle;
            cancellButton.IsEnabled = false;
            pointsListView.Foreground = Brushes.Black;
            addbutton.IsEnabled = true;
            removeButton.IsEnabled = false;
            countTextBox.Clear();
        }
        private void pointsListView_MouseUp(object sender, MouseButtonEventArgs e)
        {
            countTextBox.Clear();
            if (selectionChanged)
            {
                currentCycleNode = currentPoint.FirstCycleNode;
                selectionChanged = false;
            }
            else
            {
                if (currentCycleNode != null && currentCycleNode.Next != null)
                    currentCycleNode = currentCycleNode.Next;
                else
                    currentCycleNode = currentPoint.FirstCycleNode;
            }
        }
        private void pointsListView_MouseUp2(object sender, MouseButtonEventArgs e)
        {
            if (pointsListView.SelectedItems.Count == 1 && (creatableCycle.CycleStart == null && creatableCycle.CycleEnd == null))
            {
                creatableCycle.CycleStart = pointsStringsDictionary[(string)pointsListView.SelectedItem];
                okButton.IsEnabled = false;
            }
            else if (pointsListView.SelectedItems.Count == 2 && creatableCycle.CycleStart != null && creatableCycle.CycleEnd == null)
            {
                PointControl end = pointsStringsDictionary[(string)pointsListView.SelectedItems[1]];
                if (end.Number > creatableCycle.CycleStart.Number)
                {
                    if (end.FirstCycleNode != null)
                    {
                        LinkedListNode<CycleInfo> node = end.FirstCycleNode;
                        while (node != null && node.Value.CycleStart != creatableCycle.CycleStart)
                            node = node.Next;
                        if (node != null)
                        {
                            if (node.Value.CycleStart == creatableCycle.CycleStart && node.Value.CycleEnd == end)
                            {
                                MessageBox.Show("Такой цикл уже существует");
                                pointsListView.SelectedItems.Remove(pointsListView.SelectedItems[1]);
                                return;
                            }
                        }
                    }
                    PointControl iteratePC = creatableCycle.CycleStart;
                    bool correctInterval = true;
                    while (iteratePC != end && correctInterval)
                    {
                        foreach (CycleInfo ci in iteratePC.Cycles)
                        {
                            bool b1 = Between(ci.CycleStart, creatableCycle.CycleStart, end);
                            bool b2 = Between(ci.CycleEnd, creatableCycle.CycleStart, end);
                            if (b1 != b2)
                            {
                                correctInterval = false;
                                break;
                            }
                        }
                        iteratePC = iteratePC.NextPoint;
                    }
                    if (!correctInterval)
                    {
                        MessageBox.Show("Указанный цикл не удовлетворяет условиям вложенности и последовательности");
                        pointsListView.SelectedItems.Remove(pointsListView.SelectedItems[1]);
                        return;
                    }
                    creatableCycle.CycleEnd = end;
                    int i = 0;
                    while (i < pointsListView.Items.Count && pointsStringsDictionary[(string)pointsListView.Items[i]] != creatableCycle.CycleStart)
                        i++;
                    do
                    {
                        pointsListView.SelectedItems.Add(pointsListView.Items[i]);
                        i++;
                    }
                    while (i < pointsListView.Items.Count && pointsStringsDictionary[(string)pointsListView.Items[i]] != creatableCycle.CycleEnd);
                    if (i == pointsListView.Items.Count)
                        throw new Exception();
                    countTextBox.Focus();
                    okButton.IsEnabled = true;
                }
                else
                    pointsListView.SelectedItems.Remove(pointsListView.SelectedItems[1]);
            }
            else
            {
                pointsListView.SelectedItems.Clear();
                creatableCycle.CycleStart=null;
                creatableCycle.CycleEnd=null;
            }
        }
        //метод, определяющий, находится ли первая точка между второй и третьей
        private bool Between(PointControl targetPoint,PointControl leftBound,PointControl rightBound)
        {
            PointControl iteratePoint = leftBound.NextPoint;
            bool found=false;
            do
            {
                if (iteratePoint == targetPoint)
                    found = true;
                else
                    iteratePoint = iteratePoint.NextPoint;
            }
            while(iteratePoint!=rightBound&&!found);
            return found;
        }
        private void pointsListView_MouseDown(object sender, MouseButtonEventArgs e)
        {
            pointsListView.SelectedItems.Clear();
        }
        private void pointsListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (pointsListView.SelectedItems.Count == 1)
            {
                PointControl pc = pointsStringsDictionary[(string)pointsListView.SelectedItems[0]];
                if (pc != currentPoint)
                {
                    selectionChanged = true;
                    currentPoint = pc;
                }
            }
            
            
            //if (pointsListView.SelectedItems.Count == 1)
            //{
            //    PointControl pc = pointsStringsDictionary[(string)pointsListView.SelectedItem];
            //    if (pc.FirstCycleNode != null)
            //        currentCycleNode = pc.FirstCycleNode;
            //    else
            //        currentCycleNode = null;
            //    currentPoint = pc;
            //}
        }
        CycleInfo creatableCycle = null;
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            creatableCycle = new CycleInfo();
            pointsListView.SelectedItems.Clear();
            pointsListView.SelectionChanged -= searchingSelectionHandle;
            pointsListView.MouseUp -= searchingButtonHandle;
            pointsListView.PreviewMouseDown -= previewMouseDown;
            pointsListView.MouseUp += creatingButtonHandle;
            pointsListView.Foreground = Brushes.Gray;
            addbutton.IsEnabled = false;
            removeButton.IsEnabled = false;
            cancellButton.IsEnabled = true;
        }

        private void removeButton_Click(object sender, RoutedEventArgs e)
        {
            if (_currentCycleNode != null)
            {
                _currentCycleNode.Value.BreakCycle();
                currentPoint = null;
                _currentCycleNode = null;
                pointsListView.SelectedItems.Clear();
                removeButton.IsEnabled = false;
            }
        }

        private void okButton_Click(object sender, RoutedEventArgs e)
        {
            if (pointsListView.Foreground == Brushes.Gray)
            {
                bool b = false;
                int count;
                b = Int32.TryParse(countTextBox.Text, out count);
                if (b && count > 0 && count < 1000000)
                {
                    creatableCycle.Iterations = count;
                    creatableCycle.CycleStart.AddCycle(creatableCycle);
                    creatableCycle.CycleEnd.AddCycle(creatableCycle);
                    okButton.IsEnabled = false;
                    pointsListView.MouseUp -= creatingButtonHandle;
                    pointsListView.MouseUp += searchingButtonHandle;
                    pointsListView.PreviewMouseDown += previewMouseDown;
                    pointsListView.SelectionChanged += searchingSelectionHandle;
                    cancellButton.IsEnabled = false;
                    pointsListView.Foreground = Brushes.Black;
                    pointsListView.SelectedItems.Clear();
                    addbutton.IsEnabled = true;
                    removeButton.IsEnabled = false;
                    countTextBox.Clear();
                }
                else
                    MessageBox.Show("Некорректное количество итераций");
            }
            else
            {
                int t;
                bool b=Int32.TryParse(countTextBox.Text,out t);
                if (b && t > 0 && t < 1000000)
                    _currentCycleNode.Value.Iterations = t;
                else
                    MessageBox.Show("Некорректное количество итераций");
            }
        }

        private void cancellButton_Click(object sender, RoutedEventArgs e)
        {
            okButton.IsEnabled = false;
            pointsListView.MouseUp -= creatingButtonHandle;
            pointsListView.MouseUp += searchingButtonHandle;
            pointsListView.PreviewMouseDown += previewMouseDown;
            pointsListView.SelectionChanged += searchingSelectionHandle;
            cancellButton.IsEnabled = false;
            pointsListView.Foreground = Brushes.Black;
            addbutton.IsEnabled = true;
            removeButton.IsEnabled = false;
            countTextBox.Clear();
            pointsListView.SelectedItems.Clear();
        }
        public event SelectionChangedEventHandler SelectionChanged
        {
            add
            {
                pointsListView.SelectionChanged += value;
            }
            remove
            {
                pointsListView.SelectionChanged -= value;
            }
        }
        public IEnumerable<PointControl> SelectedPoints
        {
            get
            {
                foreach (object obj in pointsListView.SelectedItems)
                {
                    yield return pointsStringsDictionary[(string)obj];
                }
            }
        }
    }
}
